import requests
import json
import time
import base64
import hmac
import hashlib
import urllib.parse
from datetime import datetime, timezone
import os
from setting import *

class AliyunCommentDetector:
    def __init__(self, access_key_id, access_key_secret, region='cn-hangzhou'):
        """
        初始化阿里云内容安全评论检测器
        
        参数:
            access_key_id: 阿里云AccessKey ID
            access_key_secret: 阿里云AccessKey Secret
            region: 服务区域 (默认: cn-shanghai)
        """
        self.access_key_id = access_key_id
        self.access_key_secret = access_key_secret
        self.region = region
        self.endpoint = f'https://saf.{region}.aliyuncs.com'
        
        # 公共参数
        self.common_params = {
            'Format': 'JSON',
            'Version': '2020-07-06',
            'SignatureMethod': 'Hmac-SHA1',
            'SignatureVersion': '1.0',
            'AccessKeyId': self.access_key_id
        }
    
    def _generate_signature(self, params):
        """
        生成API请求签名
        
        参数:
            params: 所有请求参数
            
        返回:
            签名字符串
        """
        # 1. 排序参数
        sorted_params = sorted(params.items())
        
        # 2. 构造规范化查询字符串
        canonicalized_query_string = ''
        for (k, v) in sorted_params:
            canonicalized_query_string += '&' + self._percent_encode(k) + '=' + self._percent_encode(v)
        
        # 移除开头的'&'
        canonicalized_query_string = canonicalized_query_string[1:]
        
        # 3. 构造签名字符串
        string_to_sign = 'GET&%2F&' + self._percent_encode(canonicalized_query_string)
        
        # 4. 计算签名
        key = self.access_key_secret + '&'
        h = hmac.new(key.encode('utf-8'), string_to_sign.encode('utf-8'), hashlib.sha1)
        signature = base64.b64encode(h.digest()).decode('utf-8')
        
        return signature
    
    def _percent_encode(self, s):
        """
        URL编码
        
        参数:
            s: 要编码的字符串
            
        返回:
            编码后的字符串
        """
        if not isinstance(s, str):
            s = str(s)
        return urllib.parse.quote(s, safe='').replace('+', '%20').replace('*', '%2A').replace('%7E', '~')
    
    def _get_timestamp(self):
        """获取当前UTC时间戳"""
        return datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
    
    def detect_comment(self, comment, service='comment_detection', data_id=None, context=None):
        """
        检测评论内容
        
        参数:
            comment: 要检测的评论文本
            service: 服务类型 (默认: comment_detection)
            data_id: 数据唯一标识 (可选)
            context: 上下文信息 (可选)
            
        返回:
            检测结果字典
        """
        try:
            # 构造服务参数
            service_params = {
                'content': comment
            }
            
            # 添加可选参数
            if data_id:
                service_params['dataId'] = data_id
            if context:
                service_params.update(context)
            
            # 构造请求参数
            params = {
                **self.common_params,
                'Action': 'ExecuteRequest',
                'Service': service,
                'ServiceParameters': json.dumps(service_params),
                'Timestamp': self._get_timestamp(),
                'SignatureNonce': str(int(time.time() * 1000))  # 使用时间戳作为随机数
            }
            
            # 生成签名
            signature = self._generate_signature(params)
            params['Signature'] = signature
            
            response = requests.get(self.endpoint, params=params)
            
            if response.status_code != 200:
                return {
                    'status': 'error',
                    'code': response.status_code,
                    'message': 'API请求失败',
                    'raw_response': response.text
                }
            
            # 解析响应
            result = response.json()
            
            # 检查响应状态
            if result.get('Code') != 200:
                return {
                    'status': 'error',
                    'code': result.get('Code'),
                    'message': result.get('Message'),
                    'request_id': result.get('RequestId')
                }
            
            # 提取检测结果
            data = result.get('Data', {})
            
            # 标准化结果
            normalized = self._normalize_result(data)
            
            return normalized
            
        except Exception as e:
            return {
                'status': 'error',
                'code': 500,
                'message': str(e),
                'error_type': type(e).__name__
            }
    
    def _normalize_result(self, data):
        """
        标准化检测结果
        
        参数:
            data: API返回的原始数据
            
        返回:
            标准化的结果字典
        """
        # 风险等级到建议的映射
        risk_to_suggestion = {
            'none': 'pass',
            'low': 'review',
            'medium': 'review',
            'high': 'block',
            'review': 'review',
            'block': 'block'
        }
        
        # 标签到风险等级的映射
        label_to_risk = {
            'normal': 'none',
            'spam': 'low',
            'ad': 'medium',
            'politics': 'high',
            'terrorism': 'high',
            'abuse': 'medium',
            'porn': 'high',
            'flood': 'low',
            'contraband': 'high',
            'meaningless': 'low',
            'customized': 'medium'
        }
        
        # 提取基本结果
        risk_level = data.get('riskLevel', 'none').lower()
        
        # 提取结果细节
        results = data.get('results', [])
        if results:
            primary_result = results[0]
            label = primary_result.get('label', 'normal').lower()
            confidence = float(primary_result.get('confidence', 0))
            
            # 如果有多个结果，收集次要标签
            secondary_labels = []
            if len(results) > 1:
                for res in results[1:]:
                    if 'label' in res:
                        secondary_labels.append(res['label'].lower())
        else:
            label = 'normal'
            confidence = 1.0
            secondary_labels = []
        
        # 根据标签确定风险等级（如果API未提供）
        if risk_level == 'none':
            risk_level = label_to_risk.get(label, 'none')
        
        return {
            'status': 'success',
            'suggestion': risk_to_suggestion.get(risk_level, 'review'),
            'label': label,
            'confidence': confidence,
            'risk_level': risk_level,
            'data_id': data.get('dataId', ''),
            'content': data.get('content', ''),
            'details': {
                'secondary_labels': secondary_labels,
                'risk_interpretation': {
                    'none': "无风险内容",
                    'low': "低风险内容",
                    'medium': "中风险内容",
                    'high': "高风险内容"
                }.get(risk_level, "未知风险级别")
            }
        }
    
    def generate_report(self, result, original_comment):
        """生成可读的检测报告"""
        if result.get('status') != 'success':
            return f"检测失败: {result.get('message', '未知错误')}"
        
        risk_colors = {
            'none': '\033[92m',    # 绿色
            'low': '\033[93m',     # 黄色
            'medium': '\033[33m',  # 橙色
            'high': '\033[91m',    # 红色
            'unknown': '\033[90m'  # 灰色
        }
        reset_color = '\033[0m'
        
        risk_level = result.get('risk_level', 'unknown')
        color = risk_colors.get(risk_level, '\033[90m')
        
        report = [
            f"评论检测报告 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            f"原始评论: {original_comment}",
            "",
            f"检测结果: {color}{result.get('suggestion', 'unknown').upper()}{reset_color}",
            f"风险等级: {color}{risk_level.upper()}{reset_color}",
            f"主要标签: {result.get('label', 'unknown')}",
            f"置信度: {result.get('confidence', 0.0):.2%}",
            ""
        ]
        
        # 添加详细信息
        details = result.get('details', {})
        if 'secondary_labels' in details and details['secondary_labels']:
            report.append(f"次要标签: {', '.join(details['secondary_labels'])}")
        
        if 'risk_interpretation' in details:
            report.append(f"风险说明: {details['risk_interpretation']}")
        
        return "\n".join(report)


if __name__ == '__main__':
    # 从环境变量获取敏感信息（更安全的方式）

    # 创建评论检测器
    detector = AliyunCommentDetector(ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET)
    
    # 测试评论样本
    comment = "这个产品真的很棒，强烈推荐给大家！";
        
    # 调用检测
    result = detector.detect_comment(comment)
    
    # 生成报告
    report = detector.generate_report(result, comment)
    print("\n" + report)

